﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using Giraffe.Core.Common;
using Microsoft.Practices.Composite.Presentation.Regions;
using Microsoft.Practices.Composite.Regions;

namespace Giraffe.Client.Common.WindowsController
{
    public class WindowsController: IWindowsController
    {
        public static string MainWindowName = "MainWindow";
        private readonly Dictionary<string, Window> _windows = new Dictionary<string, Window>();

        //public IWindowSettings CreateMainWindow(ViewModelBase content)
        //{
        //    IWindowSettings settings = CreateWindow(MainWindowName, content, true);
        //    settings.ResizeMode = ResizeMode.CanMinimize;
        //    settings.WindowStartupLocation = WindowStartupLocation.CenterScreen;
        //    return settings;
        //}

        public IWindowSettings CreateWindow(string windowName, object content)
        {
            return CreateWindow(windowName, content, false);
        }

        public IWindowSettings GetWindowSettings(string windowName)
        {
            if (!_windows.ContainsKey(windowName)) return null;

            return new WindowSettings(_windows[windowName]);
        }

        public bool GetIsWindowPresent(string windowName)
        {
            return _windows.ContainsKey(windowName);
        }

        public bool? ShowWindow(string windowName, bool isModal)
        {
            IApplicationProxy applicationProxy = ObjectProvider.Resolve<IApplicationProxy>();
            if (!applicationProxy.UIDispatcher.CheckAccess())
            {
                return (bool?)applicationProxy.UIDispatcher.Invoke(new Func<string, bool, bool?>(ShowWindow), windowName, isModal);
            }

            if (!_windows.ContainsKey(windowName))
            {
                throw new ArgumentException(string.Format("Window \"{0}\" not found", windowName));
            }

            Window wind = _windows[windowName];
            Window parent = GetActiveWindow();
            if (!wind.Equals(parent))
            {
                wind.Owner = parent;
            }
            
            if (isModal)
            {
                return wind.ShowDialog();
            }
            wind.Show();
            wind.WindowState = WindowState.Normal;
            wind.Activate();
            return null;
        }

        public bool? ShowWindow(string windowName, bool isModal, string title)
        {
            IWindowSettings settings = CreateWindow(windowName, windowName);
            settings.Title = title;
            return ShowWindow(windowName, isModal);
        }

        public void CloseWindow(string windowName)
        {
            _windows[windowName].Close();
        }

        public void SetRegionManager(string windowName, IRegionManager regionManager)
        {
            IApplicationProxy applicationProxy = ObjectProvider.Resolve<IApplicationProxy>();
            if (!applicationProxy.UIDispatcher.CheckAccess())
            {
                applicationProxy.UIDispatcher.Invoke(new Action<string, IRegionManager>(SetRegionManager), windowName, regionManager);    
                return;
            }

            if (!_windows.ContainsKey(windowName)) return;

            RegionManager.SetRegionManager(_windows[windowName], regionManager);
            RegionManager.UpdateRegions();
        }


        private IWindowSettings CreateWindow(string windowName, object content, bool isMain)
        {
            IApplicationProxy applicationProxy = ObjectProvider.Resolve<IApplicationProxy>();
            if (!applicationProxy.UIDispatcher.CheckAccess())
            {
                var res = applicationProxy.UIDispatcher.Invoke(new Func<string, object, bool, IWindowSettings>(CreateWindow), windowName, content, isMain);
                    //(Action)(() => CreateWindow(windowName, content, isMain)));
                return (IWindowSettings)res;
            }

            if (_windows.ContainsKey(windowName)) return null;

            var window = new Window();
            if (isMain)
            {
                //window.Closing += MainWindow_Closing;
                Application.Current.MainWindow = window;
            }

            window.Content = content;
            window.MinHeight = 100;
            window.MinWidth = 100;
            window.Closed += Window_Closed;
            _windows[windowName] = window;

            return new WindowSettings(window);
        }

        private void Window_Closed(object sender, EventArgs e)
        {
            var closedWindow = sender as Window;
            if (closedWindow == null) return;

            closedWindow.Closed -= Window_Closed;

            foreach (KeyValuePair<string, Window> pair in _windows)
            {
                if (pair.Value == closedWindow)
                {
                    _windows.Remove(pair.Key);

                    //Todo. Need to check how it works. I don't shure that this code is really necessary
                    var disposableContent = closedWindow.Content as IDisposable;
                    if (disposableContent != null)
                    {
                        disposableContent.Dispose();
                    }

                    break;
                }
            }

        }

        private Window GetActiveWindow()
        {
            foreach (Window wind in Application.Current.Windows)
            {
                if (wind.IsActive)
                {
                    return wind;
                }
            }
            return Application.Current.MainWindow;
        }
    }
}